home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
comm
/
suncom.zip
/
TPZ.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1988-09-18
|
50KB
|
1,883 lines
UNIT TPZ;
INTERFACE
USES Crt, Dos, TPZasync, TPZVideo, TPZFiles, TPZunix, TPZcrc;
FUNCTION Zmodem_Receive(path: STRING; comport: WORD; baudrate: LONGINT): BOOLEAN;
FUNCTION Zmodem_Send(pathname: STRING; lastfile: BOOLEAN; comport: WORD; baudrate: LONGINT): BOOLEAN;
IMPLEMENTATION
CONST
TPZVER = 'TPZ [Zmodem] 2.1ß';
ZBUFSIZE = 1024;
zport: WORD = 1;
zbaud: LONGINT = 0;
TYPE
hdrtype = ARRAY[0..3] OF BYTE;
buftype = ARRAY[0..1023] OF BYTE;
CONST
ZPAD = 42; { '*' }
ZDLE = 24; { ^X }
ZDLEE = 88;
ZBIN = 65; { 'A' }
ZHEX = 66; { 'B' }
ZBIN32 = 67;{ 'C' }
ZRQINIT = 0;
ZRINIT = 1;
ZSINIT = 2;
ZACK = 3;
ZFILE = 4;
ZSKIP = 5;
ZNAK = 6;
ZABORT = 7;
ZFIN = 8;
ZRPOS = 9;
ZDATA = 10;
ZEOF = 11;
ZFERR = 12;
ZCRC = 13;
ZCHALLENGE = 14;
ZCOMPL = 15;
ZCAN = 16;
ZFREECNT = 17;
ZCOMMAND = 18;
ZSTDERR = 19;
ZCRCE = 104; { 'h' }
ZCRCG = 105; { 'i' }
ZCRCQ = 106; { 'j' }
ZCRCW = 107; { 'k' }
ZRUB0 = 108; { 'l' }
ZRUB1 = 109; { 'm' }
ZOK = 0;
ZERROR = -1;
ZTIMEOUT = -2;
RCDO = -3;
FUBAR = -4;
GOTOR = 256;
GOTCRCE = 360; { 'h' OR 256 }
GOTCRCG = 361; { 'i' " " }
GOTCRCQ = 362; { 'j' " " }
GOTCRCW = 363; { 'k' " " }
GOTCAN = 272; { CAN OR " }
{ xmodem paramaters }
CONST
ENQ = 5;
CAN = 24;
XOFF = 19;
XON = 17;
SOH = 1;
STX = 2;
EOT = 4;
ACK = 6;
NAK = 21;
CPMEOF = 26;
{ byte positions }
CONST
ZF0 = 3;
ZF1 = 2;
ZF2 = 1;
ZF3 = 0;
ZP0 = 0;
ZP1 = 1;
ZP2 = 2;
ZP3 = 3;
{ bit masks for ZRINIT }
CONST
CANFDX = 1; { can handle full-duplex (yes for PC's)}
CANOVIO = 2; { can overlay disk and serial I/O (ditto) }
CANBRK = 4; { can send a break - True but superfluous }
CANCRY = 8; { can encrypt/decrypt - not defined yet }
CANLZW = 16; { can LZ compress - not defined yet }
CANFC32 = 32; { can use 32 bit crc frame checks - true }
ESCALL = 64; { escapes all control chars. NOT implemented }
ESC8 = 128; { escapes the 8th bit. NOT implemented }
{ bit masks for ZSINIT }
CONST
TESCCTL = 64;
TESC8 = 128;
{ paramaters for ZFILE }
CONST
{ ZF0 }
ZCBIN = 1;
ZCNL = 2;
ZCRESUM = 3;
{ ZF1 }
ZMNEW = 1; {I haven't implemented these as of yet - most are}
ZMCRC = 2; {superfluous on a BBS - Would be nice from a comm}
ZMAPND = 3; {programs' point of view however }
ZMCLOB = 4;
ZMSPARS = 5;
ZMDIFF = 6;
ZMPROT = 7;
{ ZF2 }
ZTLZW = 1; {encryption, compression and funny file handling }
ZTCRYPT = 2; {flags - My docs (03/88) from OMEN say these have}
ZTRLE = 3; {not been defined yet }
{ ZF3 }
ZCACK1 = 1; {God only knows... }
VAR
rxpos: LONGINT; {file position received from Z_GetHeader}
rxhdr: hdrtype; {receive header var}
rxtimeout,
rxtype,
rxframeind: INTEGER;
attn: buftype;
secbuf: buftype;
fname: STRING;
fmode: INTEGER;
ftime,
fsize: LONGINT;
usecrc32: BOOLEAN;
zcps, zerrors: WORD;
txpos: LONGINT;
txhdr: hdrtype;
ztime: LONGINT;
CONST
lastsent: BYTE = 0;
FUNCTION Z_SetTimer: LONGINT;
VAR
l: LONGINT;
h,m,s,x: WORD;
BEGIN
GetTime(h,m,s,x);
l := LONGINT(h) * 3600;
l := l + LONGINT(m) * 60;
l := l + LONGINT(s);
Z_SetTimer := l
END;
FUNCTION Z_FileCRC32(VAR f: FILE): LONGINT;
VAR
fbuf: buftype;
crc: LONGINT;
bread, n: INTEGER;
BEGIN {$I-}
crc := $FFFFFFFF;
Seek(f,0);
IF (IOresult <> 0) THEN
{null};
REPEAT
BlockRead(f,fbuf,ZBUFSIZE,bread);
FOR n := 0 TO (bread - 1) DO
crc := UpdC32(fbuf[n],crc)
UNTIL (bread < ZBUFSIZE) OR (IOresult <> 0);
Seek(f,0);
IF (IOresult <> 0) THEN
{null};
Z_FileCRC32 := crc
END; {$I+}
FUNCTION Z_GetByte(tenths: INTEGER): INTEGER;
(* Reads a byte from the modem - Returns RCDO if *)
(* no carrier, or ZTIMEOUT if nothing received *)
(* within 'tenths' of a second. *)
VAR
n: INTEGER;
BEGIN
REPEAT
IF (NOT Z_Carrier) THEN
BEGIN
Z_GetByte := RCDO; { nobody to talk to }
Exit
END;
IF (Z_CharAvail) THEN
BEGIN
Z_GetByte := Z_ReceiveByte; { got character }
Exit
END;
Dec(tenths); { dec. the count }
Delay(100) { pause 1/10th sec. }
UNTIL (tenths <= 0);
Z_GetByte := ZTIMEOUT { timed out }
END;
FUNCTION Z_qk_read: INTEGER;
(* Just like Z_GetByte, but timeout value is in *)
(* global var rxtimeout. *)
BEGIN
Z_qk_read := Z_GetByte(rxtimeout)
END;
FUNCTION Z_TimedRead: INTEGER;
(* A Z_qk_read, that strips parity and *)
(* ignores XON/XOFF characters. *)
VAR
done: BOOLEAN;
c: INTEGER;
BEGIN
done := FALSE;
REPEAT
c := Z_qk_read AND $FF7F { strip parity }
UNTIL (c < 0) OR (NOT (Lo(c) IN [17,19])); { wait for other than XON/XOFF }
Z_TimedRead := c
END;
PROCEDURE Z_SendCan;
(* Send a zmodem CANcel sequence to the other guy *)
(* 8 CANs and 8 backspaces *)
VAR
n: BYTE;
BEGIN
Z_ClearOutbound; { spare them the junk }
FOR n := 1 To 8 DO
BEGIN
Z_SendByte(CAN);
Delay(100) { the pause seems to make reception of the sequence }
END; { more reliable }
FOR n := 1 TO 10 DO
Z_SendByte(8)
END;
PROCEDURE Z_PutString(VAR p: buftype);
(* Outputs an ASCII-Z type string (null terminated) *)
(* Processes meta characters 221 (send break) and *)
(* 222 (2 second delay). *)
VAR
n: INTEGER;
BEGIN
n := 0;
WHILE (n < ZBUFSIZE) AND (p[n] <> 0) DO
BEGIN
CASE p[n] OF
221 : Z_SendBreak;
222 : Delay(2000)
ELSE
Z_SendByte(p[n])
END;
Inc(n)
END
END;
PROCEDURE Z_PutHex(b: BYTE);
(* Output a byte as two hex digits (in ASCII) *)
(* Uses lower case to avoid confusion with *)
(* escaped control characters. *)
CONST
hex: ARRAY[0..15] OF CHAR = '0123456789abcdef';
BEGIN
Z_SendByte(Ord(hex[b SHR 4])); { high nybble }
Z_SendByte(Ord(hex[b AND $0F])) { low nybble }
END;
PROCEDURE Z_SendHexHeader(htype: BYTE; VAR hdr: hdrtype);
(* Sends a zmodem hex type header *)
VAR
crc: WORD;
n, i: INTEGER;
BEGIN
Z_SendByte(ZPAD); { '*' }
Z_SendByte(ZPAD); { '*' }
Z_SendByte(ZDLE); { 24 }
Z_SendByte(ZHEX); { 'B' }
Z_PutHex(htype);
crc := UpdCrc(htype,0);
FOR n := 0 TO 3 DO
BEGIN
Z_PutHex(hdr[n]);
crc := UpdCrc(hdr[n],crc)
END;
crc := UpdCrc(0,crc);
crc := UpdCrc(0,crc);
Z_PutHex(Lo(crc SHR 8));
Z_PutHex(Lo(crc));
Z_SendByte(13); { make it readable to the other end }
Z_SendByte(10); { just in case }
IF (htype <> ZFIN) AND (htype <> ZACK) THEN
Z_SendByte(17); { Prophylactic XON to assure flow }
IF (NOT Z_Carrier) THEN
Z_ClearOutbound
END;
FUNCTION Z_PullLongFromHeader(VAR hdr: hdrtype): LONGINT;
(* Stuffs a longint into a header variable - N.B. - bytes are REVERSED! *)
VAR
l: LONGINT;
BEGIN
l := hdr[ZP3]; { hard coded for efficiency }
l := (l SHL 8) OR hdr[ZP2];
l := (l SHL 8) OR hdr[ZP1];
l := (l SHL 8) OR hdr[ZP0];
Z_PullLongFromHeader := l
END;
PROCEDURE Z_PutLongIntoHeader(l: LONGINT);
(* Reverse of above *)
BEGIN
txhdr[ZP0] := BYTE(l);
txhdr[ZP1] := BYTE(l SHR 8);
txhdr[ZP2] := BYTE(l SHR 16);
txhdr[ZP3] := BYTE(l SHR 24)
END;
FUNCTION Z_GetZDL: INTEGER;
(* Gets a byte and processes for ZMODEM escaping or CANcel s